/*******************************************************************************
 * 版权：北京润尼尔网络科技有限公司，保留所有版权<br>
 * 版本：v1.0.0<br>
 * 文件：ConnectionModel.js<br>
 * 日期：2016年9月19日<br>
 * 作者: 王志远<br>
 * 功能：连接模型<br>
 * 
 * 修改记录：<br>
 * 日期 描述 更新功能<br>
 ******************************************************************************/

window.makeNamespace(window,"Rainier.UI.V2");

/**
 * 类型名称：Rainier.UI.V2.ConnectionModel<br>
 * 类型功能：连接模型<br>
 */
Rainier.UI.V2.ConnectionModel = Rainier.UI.V2.CompositeModel.extend({
	
	NAME : "Rainier.UI.V2.ConnectionModel",
		
	/**
	 * 函数名称：Rainier.UI.V2.ConnectionModel.init<br>
	 * 函数功能：构造函数<br>
	 * 参数输入:property<br>
	 *    	{
	 *     		type:Rainier.UI.V2.ConnectionModel,
	 *     		id	:'111-111-111-112',
	 *     		uiProperty:{
	 * 				outlineStroke	:3
	 * ,
	 *   			outlineColor	:'#303030',
	 *   			stroke			:1,
	 *   			radius			:5,
	 *   			color			:'#00A8F0'
	 *     		},
	 *     
	 *     		modelProperty:{
	 *     			name	: 'connection1',
	 *     			router	: 'Rainier.UI.V2.InteractiveManhattanRouter',
	 *     			segments:[
	 *     				{start_x:100,start_y:100,end_x:200,end_y:200,type='horizontal'},
	 *     				{start_x:100,start_y:100,end_x:200,end_y:200,type='vertical'},
	 *     				{start_x:100,start_y:100,end_x:200,end_y:200,type='horizontal'},
	 *     			],
	 *     			source_id : 'xxxx-xxxx-xxxx-xxxx',
	 *     			target_id : 'xxxx-xxxx-xxxx-xxxx',
	 *     		},
	 *     	},
	 * 异常信息：无<br>
	 */
	init : function(property){
		var dummy = jQuery.extend(true,{},property);
		this._super(dummy);
		this.sourcePort = null;
		this.targetPort = null;
		
		/*连线类型*/
		this.DEVICE_TO_DEVICE 		 = "DEVICE_TO_DEVICE";
		this.DEVICE_TO_JOINTMODEL	 = "DEVICE_TO_JOINTMODEL";
		this.JOINTMODEL_TO_DEVICE    = "JOINTMODEL_TO_DEVICE";
		this.JOINTMODEL_TO_JOINTMODEL= "JOINTMODEL_TO_JOINTMODEL";
	},
	
	/**
	 * 函数名称：Rainier.UI.V2.CompositeModel.serializeToJson<br>
	 * 函数功能：将对象串行化为Json对象<br>
	 * 函数返回：json对象<br>
	 * 异常信息：无<br>
	 */
	serializeToJson : function(){
		var json  = this._super();
		console.log(json)
		json.type = "Rainier.UI.V2.ConnectionModel";
		json.modelProperty.source_id = this.sourcePort.getUuid();
		json.modelProperty.target_id = this.targetPort.getUuid();
		json.modelProperty.label = this.label;
		json.modelProperty.source_parent_id = this.sourcePort.getParent() ? this.sourcePort.getParent().getUuid() : "";
		json.modelProperty.target_parent_id = this.targetPort.getParent() ? this.targetPort.getParent().getUuid() : "";
		delete json.uiProperty.vertices;
		delete json.uiProperty.x;
		delete json.uiProperty.y;
		delete json.uiProperty.needCommandRequest;
		return json;
	},
	
	/**
	 * 函数名称：Rainier.UI.V2.ConnectionModel.clone<br>
	 * 函数功能：对象拷贝<br>
	 * 参数输入：无<br>
	 * 参数输出：无<br>
	 * 函数返回：Rainier.UI.V2.ConnectionModel<br>
	 * 异常信息：无<br>
	 */
	clone : function(){
		//注：当copy连线的时候，应该考虑其，source和target，同时应关注其对应的入度和出度。
		if(!this.duplicate){
			this.duplicate = eval('new '+this.NAME+'(this.getProperty())');
			//this.duplicate = new Rainier.UI.V2.ConnectionModel(this.getProperty());
		}
		
		var _this = this;
		//此处对连线上的jointModel进行一下简单的处理；
		var jointModelArray = this.getChildren();		//copy连线的jointModel
		this.duplicate.clearChildren();
		if(jointModelArray.length>0){
			jointModelArray.forEach(function(jointModel,index,jointModelArray){
				$.proxy(_this.duplicate.addChildModel(
						jointModel.duplicate?jointModel.duplicate:jointModel.clone()),_this.duplicate);
				//下面这句可有可无：添加以显示代码行为的相似性。
				jointModel.duplicate.setParent(_this.duplicate);
			});
		}
		
		var sourcePortDup = (this.sourcePort.duplicate)?this.sourcePort.duplicate:this.sourcePort.clone();
		var targetPortDup = (this.targetPort.duplicate)?this.targetPort.duplicate:this.targetPort.clone();
		
		this.duplicate.sourcePort = sourcePortDup;
		this.duplicate.targetPort = targetPortDup;
		this.duplicate.setParent(this.getParent());
		
		//sourcePort和targerPort 与当前连线的关联 删除
		sourcePortDup.detachOutgoing(this);
		targetPortDup.detachIncoming(this);
		
		//sourcePort和targerPort当前连线副本进行关联 并把当前连线关联到这连个port上
		this.duplicate.attachSourcePort(sourcePortDup);
		this.duplicate.attachTargetPort(targetPortDup);
		sourcePortDup.attachOutgoing(this.duplicate);
		targetPortDup.attachIncoming(this.duplicate);
		
		return this.duplicate;
	},
	
	/**
	 * 函数名称：Rainier.UI.V2.ConnectionModel.clearDuplicate<br>
	 * 函数功能：清除拷贝对象<br>
	 * 参数输入：无<br>
	 * 参数输出：无<br>
	 * 函数返回：无<br>
	 * 异常信息：无<br>
	 */
	clearDuplicate : function(){
		var jointModelArray = this.getChildren();
		
		jointModelArray.forEach(function(jointModel,index,jointModelArray){
			jointModel.clearDuplicate();
		});
		
		this.duplicate = null;
	},
	
	/**
	 * 函数名称：Rainier.UI.V2.ConnectionModel.attachSourcePort<br>
	 * 函数功能：关联源端口<br>
	 * 参数输入：port:Rainier.UI.V2.AbstractPortModel<br>
	 * 函数返回：无<br>
	 * 异常信息：无<br>
	 */
	attachSourcePort : function(port){
		this.sourcePort = port;
		var event = Rainier.UI.V2.ConnectionModel.MODEL_EVENT_ATTACH_SOURCE_PORT;
		this.firePropertyChange(
				event, 
				null, 
				port
		);
	},
	
	/**
	 * 函数名称：Rainier.UI.V2.ConnectionModel.detachSourcePort<br>
	 * 函数功能：分离源端口<br>
	 * 参数输入：port:Rainier.UI.V2.AbstractPortModel<br>
	 * 函数返回：无<br>
	 * 异常信息：无<br>
	 */
	detachSourcePort : function(port){
		this.sourcePort = null;
		var event = Rainier.UI.V2.ConnectionModel.MODEL_EVENT_DETACH_SOURCE_PORT;
		this.firePropertyChange(
				event, 
				null, 
				port
		);
	},
	
	/**
	 * 函数名称：Rainier.UI.V2.ConnectionModel.attachTargetPort<br>
	 * 函数功能：关联目标端口<br>
	 * 参数输入：port:Rainier.UI.V2.AbstractPortModel<br>
	 * 函数返回：无<br>
	 * 异常信息：无<br>
	 */
	attachTargetPort : function(port){
		this.targetPort = port;
		var event = Rainier.UI.V2.ConnectionModel.MODEL_EVENT_ATTACH_TARGET_PORT;
		this.firePropertyChange(
				event, 
				null, 
				port
		);
	},
	
	/**
	 * 函数名称：Rainier.UI.V2.ConnectionModel.detachTargetPort<br>
	 * 函数功能：分离目标端口<br>
	 * 参数输入：port:Rainier.UI.V2.AbstractPortModel<br>
	 * 函数返回：无<br>
	 * 异常信息：无<br>
	 */
	detachTargetPort : function(port){
		this.targetPort = null;
		var event = Rainier.UI.V2.ConnectionModel.MODEL_EVENT_DETACH_TARGET_PORT;
		this.firePropertyChange(
				event, 
				null, 
				port
		);
	},
	
	/**
	 * 函数名称：Rainier.UI.V2.ConnectionModel.getSourcePort<br>
	 * 函数功能：获取源端口<br>
	 * 函数返回：Rainier.UI.V2.AbstractPortModel<br>
	 * 异常信息：<br>
	 */
	getSourcePort : function(){
		return this.sourcePort;
	},
	
	/**
	 * 函数名称：Rainier.UI.V2.ConnectionModel.getTargetPort<br>
	 * 函数功能：获取目标端口<br>
	 * 函数返回：Rainier.UI.V2.AbstractPortModel<br>
	 * 异常信息：<br>
	 */
	getTargetPort : function(){
		return this.targetPort;
	},
	
	/**
	 * 函数名称：Rainier.UI.V2.ConnectionModel.detachSourcePortAndTargetPort<br>
	 * 函数功能：解除连线和port的关联关系<br>
	 * 函数返回：无<br>
	 * 异常信息：无<br>
	 */
	detachSourcePortAndTargetPort : function(){
		this.sourcePort.detachOutgoing(this);
		this.targetPort.detachIncoming(this);
		this.detachSourcePort(this.sourcePort);
		this.detachTargetPort(this.targetPort);
	},
	
	/**
	 * 函数名称：Rainier.UI.V2.ConnectionModel.encapsulateConnInfo<br>
	 * 函数功能：对连线信息进行封装<br>
	 * 参数输入：无<br>
	 * 参数输出：无<br>
	 * 函数返回：connInfo：封装好的连线信息<br>
	 * 异常信息：<br>
	 */
	 encapsulateConnInfo : function(){
		if(!this.sourcePort && !this.targetPort){
			return;
		}
		var sourcePortParent = this.sourcePort.getParent();
		var targetPortParent = this.targetPort.getParent();
		if(!sourcePortParent && !targetPortParent){
			return;
		}
		
		/*******************************开始 ：将删除的信息封装成对象********************************/
		var connInfo 					= {};
		connInfo.connType 				= null;
		connInfo.connModel   			= {};
		connInfo.sourceModel	 		= {};
		connInfo.targetModel	 		= {};
		
		connInfo.connModel.connection = this;
		connInfo.connModel.sourcePort = this.getSourcePort();
		connInfo.connModel.targetPort = this.getTargetPort();
		
		if(sourcePortParent instanceof Rainier.UI.V2.DeviceModel &&
				targetPortParent instanceof Rainier.UI.V2.DeviceModel){
			//图元之间连线
			connInfo.connType 		  = this.DEVICE_TO_DEVICE;
			connInfo.sourceModel	  = null;
			connInfo.targetModel	  = null;
			
		}else if(sourcePortParent instanceof Rainier.UI.V2.JointModel &&
				targetPortParent instanceof Rainier.UI.V2.JointModel){
			//连线与连线之间的连线
			connInfo.connType 		  		= this.JOINTMODEL_TO_JOINTMODEL;
			
			connInfo.sourceModel.jointModel = sourcePortParent;
			connInfo.sourceModel.hybirdPort = sourcePortParent.getHybridPorts().get(0);
			
			connInfo.targetModel.jointModel = targetPortParent;
			connInfo.targetModel.hybirdPort = targetPortParent.getHybridPorts().get(0);
			
		}else if(sourcePortParent instanceof Rainier.UI.V2.DeviceModel &&
				targetPortParent instanceof Rainier.UI.V2.JointModel){
			//图元和连线之间的连线
			connInfo.connType 	      		= this.DEVICE_TO_JOINTMODEL;
			
			connInfo.sourceModel	 		= null;
			connInfo.targetModel.jointModel = targetPortParent;
			connInfo.targetModel.hybirdPort = targetPortParent.getHybridPorts().get(0);
			
		}else if(sourcePortParent instanceof Rainier.UI.V2.JointModel &&
						targetPortParent instanceof Rainier.UI.V2.DeviceModel){
			//图元和连线之间的连线
			connInfo.connType 		  		= this.JOINTMODEL_TO_DEVICE;
			
			connInfo.sourceModel.jointModel = sourcePortParent;
			connInfo.sourceModel.hybirdPort = sourcePortParent.getHybridPorts().get(0);
			connInfo.targetModel	 		= null;
		}
		/*******************************结束 ：将删除的信息封装成对象********************************/					
		
		return connInfo;
	},
	
	/**
	 * 函数名称：Rainier.UI.V2.ConnectionModel.getBranchConnAndJointModel<br>
	 * 函数功能：获取连线上所有的子jointModel,和对应分支连线<br>
	 * 参数输入：conn 			: 	Rainier.UI.V2.Connection	//当前需要删除的连线<br>
	 * 参数输出：connList		:  draw2d.util.ArrayList		//删除过程中，删除的所有连线<br>
	 * 异常信息：无<br>
	 */
	getBranchConnection : function(){
		var _this 			= this;
		var connList		= new draw2d.util.ArrayList();
		var conn			= this;
		connList.add(conn);
		_getChildConnection(conn,connList);
		
		/**
		 * 获取所有自连线
		 */
		function _getChildConnection(conn,connList){
			var arrJointModels  = conn.getChildren();//注：此处返回的是js原生数组。即连线上的所有jointModels
			var branchList 		= new draw2d.util.ArrayList();
			//获取当前连线上的子连线
			if(arrJointModels.length>0){
				arrJointModels.forEach(function(jointModel,index,arrPortModels){
					//第一步：获取当前连线上的所有子连线，并添加到connList中
					//获取当前portModel中的port对象
					var port 		= jointModel.getHybridPorts().get(0);
					var incomings 	= port.getIncomings();
					var outgoings 	= port.getOutgoings();
					incomings.each(function(j,c){
						branchList.add(c);
					});
					outgoings.each(function(j,c){
						branchList.add(c);
					});
				});
			}
			branchList.each(function(index,conn){
				_getChildConnection(conn,connList);
				connList.add(conn);
			});
		}
		
		return connList;
	},
	
	/**
	 * 函数名称：Rainier.UI.V2.ConnectionModel.showNodeLabel<br>
	 * 函数功能：在实验台上显示连线结点<br>
	 * 参数输入：fireEvent		:boolean是否广播事件<br>
	 * 参数输入：requestCommand:boolean是否请求命令<br>
	 * 参数输入：ommitedListener:忽略的侦听器<br>
	 * 函数返回：无<br>
	 * 异常信息：无<br>
	 */
	showNodeLabel : function(fireEvent,requestCommand,ommitedListener){
			
		var newValue = {visible:true};
		newValue.needCommandRequest = requestCommand;
		
		if(fireEvent){
			var event = Rainier.UI.V2.ConnectionModel.MODEL_EVENT_SHOW_NODE_LABEL;
			this.firePropertyChange(
					event, 
					null, 
					newValue,
					ommitedListener
			);											
		}
	},
	
	/**
	 * 函数名称：Rainier.UI.V2.ConnectionModel.showNodeLabel<br>
	 * 函数功能：在实验台上显示连线结点<br>
	 * 参数输入：fireEvent		:boolean是否广播事件<br>
	 * 参数输入：requestCommand:boolean是否请求命令<br>
	 * 参数输入：ommitedListener:忽略的侦听器<br>
	 * 函数返回：无<br>
	 * 异常信息：无<br>
	 */
	changeNodeLabel : function(fireEvent,requestCommand,ommitedListener){
		var newValue = {};
		var sourceType = this.sourcePort.portType;
		var targetType = this.targetPort.portType;

		var node = -1;

		if(this.hasChildren()){
			var childF = this.getChildren()[0];
			node = childF.hybridPorts.get(0).getProperty().modelProperty.node;
		}
		else{			
			var showNode = this.sourcePort.getProperty().modelProperty.showNode;
			if (showNode || showNode === 0) {
				node = showNode;
			}
			else{
				node = this.sourcePort.getProperty().modelProperty.node;
			}
//			var port = (sourceType === 'A')?this.sourcePort:this.targetPort;
//			node = port.getProperty().modelProperty.node;
		}
		
		newValue.nodeLabel = node;
		
		if(fireEvent){
			var event = Rainier.UI.V2.ConnectionModel.MODEL_EVENT_CHANGE_NODE_LABEL;
			this.firePropertyChange(
					event, 
					null, 
					newValue,
					ommitedListener
			);											
		}
	},
	
	/**
	 * 函数名称：Rainier.UI.V2.ConnectionModel.hideNodeLabel<br>
	 * 函数功能：在实验台上隐藏连线结点<br>
	 * 参数输入：fireEvent		:boolean是否广播事件<br>
	 * 参数输入：requestCommand:boolean是否请求命令<br>
	 * 参数输入：ommitedListener:忽略的侦听器<br> 
	 * 函数返回：无<br>
	 * 异常信息：无<br>
	 */
	hideNodeLabel : function(fireEvent,requestCommand,ommitedListener){		
		var newValue = {visible:false};
		
		newValue.needCommandRequest = requestCommand;
		if(fireEvent){
			var event = Rainier.UI.V2.ConnectionModel.MODEL_EVENT_HIDE_NODE_LABEL;
			this.firePropertyChange(
					event, 
					null, 
					newValue,
					ommitedListener
			);					
		}
	},
});

Rainier.UI.V2.ConnectionModel.MODEL_EVENT_ATTACH_SOURCE_PORT = "attach source port";	//关联源端口事件
Rainier.UI.V2.ConnectionModel.MODEL_EVENT_DETACH_SOURCE_PORT = "detach source port";	//分离源端口事件
Rainier.UI.V2.ConnectionModel.MODEL_EVENT_ATTACH_TARGET_PORT = "attach target port";	//关联目标端口事件
Rainier.UI.V2.ConnectionModel.MODEL_EVENT_DETACH_TARGET_PORT = "detach target port";	//分离目标端口事件
Rainier.UI.V2.ConnectionModel.MODEL_EVENT_ATTACH_TARGET_PORT = "attach target port";	//关联目标端口事件
Rainier.UI.V2.ConnectionModel.MODEL_EVENT_DETACH_TARGET_PORT = "detach target port";	//分离目标端口事件

Rainier.UI.V2.ConnectionModel.MODEL_EVENT_SHOW_ODE_LABEL    = "MODEL_EVENT_SHOW_NODE_LABEL";//ConnectionModel事件定义：显示结点
Rainier.UI.V2.ConnectionModel.MODEL_EVENT_HIDE_NODE_LABEL  	 = "MODEL_EVENT_HIDE_NODE_LABEL";//ConnectionModel事件定义：隐藏结点
Rainier.UI.V2.ConnectionModel.MODEL_EVENT_CHANGE_NODE_LABEL  = "MODEL_EVENT_CHANGE_NODE_LABEL";//ConnectionModel事件定义：修改结点